package com.eteng.demo.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.eteng.entity.Constants;
import com.eteng.entity.FtpConfig;

public class FileHandler {

	private FtpHelper ftpHelper = FtpHelper.getInstance();
	FtpConfig config = new FtpConfig();
	private static int SEARCH_HEAD = 1;
	private static int GENERATE_HEAD = 2;
	private static String fileName;
	
	private FileHandler(){
		
	}
	
	private static FileHandler fileHandler = new FileHandler();
	
	public static FileHandler getInstance(){
		
		fileName = "gz_189custbill_" + findLastMonFiles(GENERATE_HEAD) + ".txt";
		return fileHandler;
	}
	
	/**
	 * 获取文件
	 * @param targetPath
	 * @return
	 */
	public void getFtpFiles(String targetPath) {
	
		String strFlag = findLastMonFiles(SEARCH_HEAD);
		FTPClient client = ftpHelper.getClient(config);
//		XmlParserUtil xmlUtil = new XmlParserUtil();
		ArrayList<String> usableFileNames = new ArrayList<String>();
//		InputStream[] isList = null;
		try {
			// 获取文件根目录列表
			client.changeWorkingDirectory(Constants.FtpFromPath);
			FTPFile[] fileList = client.listFiles();
			System.out.println("开始解析文件...");
			for (FTPFile file : fileList) {
				String name = file.getName();
				//是否匹配，如：2014-6*.cb0
				if(name.startsWith(strFlag) && name.endsWith(".cb0")){
					System.out.println("检查到文件：" + name);
					usableFileNames.add(file.getName());
					//保存到指定地址
					File localFile = new File(Constants.CB0_SAVE_PATH + name); 
	                OutputStream os = new FileOutputStream(localFile);  
	                client.retrieveFile(name, os); 
	                os.close();
	                
	                //解析文件
	        		InputStream[] isList = DivideFile(client.retrieveFileStream(name));// remote
	        		client.completePendingCommand();
	        		if (isList != null) {
	        			XmlParserUtil xmlUtil = new XmlParserUtil();
	        			SAXReader reader = new SAXReader();
	        			reader.setValidation(false);
	        			if (reader.getEncoding() == null) {
	        				reader.setEncoding("gb2312");
	        			}

	        			int count = 1;
	        			for (InputStream is : isList) {
	        				try {
	        					// System.out.println("执行第 " + count + " 个。。。。");
	        					Document document = reader.read(is);
	        					Element rootElement = document.getRootElement();

	        					if (!rootElement.getName().equals("CustBillQuery")) {
	        						// System.out.println("文件非CustBillQuery");
	        						// System.out.println("document" + document.asXML());
//	        						errorCount++;
	        						continue;
	        					}
	        					// System.out.println("******执行下一个******");
	        					
	        						xmlUtil.testParseXMLData(rootElement);
	        					
	        					count++;
	        					is.close();
	        				} catch (Exception e) {
	        					if (e instanceof DocumentException) {
	        						System.out.println("第 " + count + " 文件格式有错误");
//	        						e.printStackTrace();
	        						continue;
	        					} else if(e instanceof NullPointerException){
	        						System.out.println("构造数据出错");
//	        						e.printStackTrace();
	        					}
	        					continue;
	        				}
	        			}

	        			System.out.println("成功解析了" + count + "/" + isList.length + "文件");
	        			System.out.print("准备写入文件");
	        			try{
	        				InputStream xx = null;
	        				int progress = 1;
	        				for(String str : xmlUtil.comboStrList){
	        					
	        					System.out.print("-");
								progress ++;
								if(progress > 80){
									progress = 1;
									System.out.print("\n");
								}
	        					xx = new ByteArrayInputStream(str.getBytes());
//	        					String fileName = "gz_189custbill_" + findLastMonFiles(GENERATE_HEAD) + ".txt";// new Date()为获取当前系统时间
	        					fileHandler.writeToFile(xx, Constants.GENERATE_DIR, fileName);
	        				}
	        				xx.close();
	        			} catch (Exception e) {
	        				if(e instanceof IOException){
	        					System.out.print("写入错误");
	        				}
	        				if(e instanceof ConnectException){
	        					System.out.println("服务器连接错误");
	        				}
	        				e.printStackTrace();
	        				continue;
	        			}
	        			System.out.println();
	        			System.out.print("写入完成");
	        		} else {
	        			System.out.println("inputstream is null");
	        			continue;
	        		}
				}
				
			}
			//线程完成文件
//			new Thread(new SaveFtpFile(usableFileNames, "/Users/DKY/Desktop/test/", client)).start();
		} catch (Exception e) {
			if(e instanceof FileNotFoundException){
				System.out.println("没有找到文件！！");
			}
			if(e instanceof NullPointerException){
				System.out.println("null");
				
			}
			e.printStackTrace();
			
		}
		System.out.println("解析完成，上传集团FTP服务器...");
		InputStream localFile;
		try {
			localFile = new FileInputStream(new File(Constants.GENERATE_DIR + fileName));
			uploadFile(fileName, localFile);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("文件上传失败！");
		}
		
		System.out.println("操作完毕！");
		
}
	
	/**
	 * 生成需找上一个月文件的标识
	 * @return 上个月CB0文件的年月前缀
	 */
	private static String findLastMonFiles(int HEAD){
		/**
		 * 分析：
		 * 1、找到这个上个月的日期
		 */
		
		String strFlag = "";
		Calendar c = Calendar.getInstance();
//		//测试六月份的数据
//		c.set(2014, 6, 20);
		int month = c.get(Calendar.MONTH);
		int year = c.get(Calendar.YEAR);
		int day = c.get(Calendar.DAY_OF_MONTH);
		//当年的1月份，取上一年12月份的文件
		if(month == 0){
			year = year - 1;
			month = 12;
		}
		if(HEAD == SEARCH_HEAD){
			strFlag = String.valueOf(year) + "-" + String.valueOf(month);
		} else if (HEAD == GENERATE_HEAD){
			strFlag = String.valueOf(year) + String.valueOf(month) + String.valueOf(day);
		}
		
		return strFlag;
	}
	
	/**
	 * 将流类容写入指定文件
	 * @param is 需要写入的文件流
	 * @param path 文件的保存地址
	 * @param fileName 保存文件的命名
	 * @throws IOException
	 */
	public void writeToFile(InputStream is, String path, String fileName) throws IOException{
		File file = new File(path + fileName);//windows
		if(!file.exists()){
			file.createNewFile();
		}
		
		//将内容写入文件
		BufferedWriter out = null;
		out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
		BufferedReader reader = new BufferedReader(new InputStreamReader(is, "gb2312"));
		String str = "";
		while((str = reader.readLine()) != null){
			out.write(str);
			}
		//写完换行
		out.write("\n");
		
		reader.close();
		out.close();
	}
	
	/**
	 * 将整个CB0文件中的每个订单XML分割开
	 * @param is
	 * @return
	 */
	public InputStream[] DivideFile(InputStream is) {
		BufferedReader br = null;
		String str = "";
		String[] strItemList = null;
		InputStream[] inputStreamList = null;
		ArrayList<String> noEmptyList = new ArrayList<String>();
		if(is == null){
			return null;
		}
		try {
			br = new BufferedReader(new InputStreamReader(is, "gb2312"),
					5 * 1024 * 1024);
			while ((str = br.readLine()) != null) {
				
				//指定分隔符分割文本
				strItemList = str.split("<!------split------>");		
			}
			
			if(strItemList.length < 0){
				System.out.println("分割错误");
			} else {
				
				//去除空白的行
//				int countFlag = 1;
//				int tesetCount = 1;
				for(String strItem : strItemList){
					if(strItem.equals("")){
						continue;
					} else {
						//去除</CustBillQuery>节点后的错误字符
						String endFlag = "</CustBillQuery>";
						Pattern pattern = Pattern.compile(endFlag);
						 Matcher matcher = pattern.matcher(strItem);
						 if (matcher.find()) {
						   if((strItem.indexOf(matcher.group()) + endFlag.length()) < strItem.length()){
							   strItem = strItem.substring(0, strItem.indexOf(matcher.group()) + endFlag.length());
//							   tesetCount ++;
						   }
						 }
					}
					
//					countFlag++;
					noEmptyList.add(strItem);
				}
				inputStreamList = new InputStream[noEmptyList.size()];
				
				for (int i = 0; i < noEmptyList.size(); i++){
					
					//如果字符串是空或者没有内容
					if(strItemList[i] == null){
						continue;
					}
					inputStreamList[i] = new ByteArrayInputStream(noEmptyList.get(i).getBytes());

				}				
				br.close();
				is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return inputStreamList;
	}
	
	/**
	 * 上传到FTP服务器
	 * @param input
	 * @return
	 */
	public boolean uploadFile(String fileName, InputStream input) {
		boolean success = false;
		FTPClient ftpClient = ftpHelper.getUpLoadClient(config);
		try {
			int reply;
			
			reply = ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftpClient.disconnect();
				return success;
			}
			ftpClient.changeWorkingDirectory(Constants.ENTERPRISE_DIR);
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			
			ftpClient.storeFile(new String(fileName.getBytes("GB2312"),"iso-8859-1"), input);
			ftpClient.storeFile(fileName, input);
			
			input.close();
			ftpClient.logout();
			success = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return success;
	}
}
